This implementation uses the function nextRNGStream
in package parallel
to set up streams appropriate for working on a
cluster system with MPI. The main difference from parallel
is
that it adds a reproducibility capability with vector-based
streams that works across different numbers of nodes or cores by associating
streams with an application vector.
Vector-based streams are best set up with the higher level function
comm.chunk
instead of using comm.set.stream
directly.
comm.chunk
will set up only the streams that each rank needs
and provides the stream numbers necessary to switch between them with
comm.set.stream
.
The function uses parallel
's
nextRNGStream()
and sets up the parallel stream seeds in the
.pbd_env$RNG
environment, which are then managed with
comm.set.stream
. There is only one communication broadcast in
this implementation that ensures all ranks have the same seed as rank 0.
Subsequently, each rank maintains only its own streams.
When rank-based streams are set up, comm.chunk
with
form = "number"
and rng = TRUE
parameters, streams are
different for each rank and switching is not needed. Vector-based streams
are obtained with form = "vector"
and rng = TRUE
parameters.
In this latter case, the vector returned to each
rank contains the stream numbers (and vector components) that the rank owns.
Switch with comm.set.stream(v)
, where v is one of the stream numbers.
Switching back and forth is allowed, with each stream continuing where it
left off.
## RNG Notes
R sessions connected by MPI begin like other R sessions as discussed in
Random
. On first use of random number generation,
each rank computes its own seed from a combination of clock time and process
id (unless it reads a previously saved workspace, which is not recommended).
Because of asynchronous execution, imperfectly synchronized node clocks,
and likely different process ids, this
almost guarantees unique seeds and most likely results in independent
streams. However, this is not reproducible and not guaranteed. Both
reproducibility and guarantee are brought by the use of the L'Ecuyer-CMRG
generator implementation in nextRNGStream
and the
use of comm.set.seed
and comm.set.stream
adaptation for
parallel computing on cluster systems.
At a high level, the L'Ecuyer-CMRG pseudo-random number generator can
take jumps (advance the seed) in its
stream (about 2^191 long) so that distant substreams can be assigned. The
nextRNGStream
implementation takes jumps of 2^127
(about 1.7e38) to provide up to 2^64 (about 1.8e19) independent streams. See
https://stat.ethz.ch/R-manual/R-devel/library/parallel/doc/parallel.pdf
for more details.
In situations that require the same stream on all ranks, a simple
set.seed
from base R and the default RNG will suffice.
comm.set.seed
will also accomplish this with the diff = FALSE
parameter if switching between same and different streams is needed.